//Header file definition for cameras
#ifndef __CAMERA_H__
#define __CAMERA_H__

#pragma once
#include "Vector.h"		//we use a 3d vector coords. When we switch to 4 coord vector notation, we implement a camera system accordingly
#include "Ray3.h"
#include "Geometry.h"
#include "ONB.h"

//Orientation enum
typedef enum Handedness
{
	LHS, RHS
}Handedness, handedness;


//class: Pinhole camera
//Desc:  This class implements a pinhole camera system
//		 Implement this as a thread safe class. Multiple threads can use the class to get rays accordingly. Initially only primary rays.
class PinholeCamera
{
public:
	//the below three data are used to form the image plane
	Vector3 position;		// position of camera
	Vector3 direction;		// direction which it is looking
	Vector3 up;				// up vector specifying the updirection of camera
	Handedness hand;		// Camera's coord systems handedness.

	float focal_length;		// focal length of the camera - distance between pinhole and projection plane
	float image_width;
	float image_height;
	

	Vector3 image_o;		//images origin
	Vector3 image_u;		//images horizontal axis
	Vector3 image_v;		//images vertical axis
 	
	ONB camera_coord;		//camera's coord system ONB

	//Constructor
	PinholeCamera();		// Default constructor
	
	// Constructor specified by location and focal length and width of image plane
	PinholeCamera(Vector3 _p, Vector3 _d, Vector3 _u, Handedness hand, float focus, float iw, float ih);		// we use copy of data rather than references for now.
	
	//functions
	Ray3 GetRay(float pixel_x, float pixel_y);		// this type of function is used for multiple threads 
													// for calling in their respective quads
	//Function to return an array of N rays for each pixel - sampling
	Ray3* GetRay(float pixel_x, float pixel_y, float nsamples, float* offset_x, float* offset_y);
};

// class: ThinLensCamera
// Desc: This class is designed by using the thin lens model
//		 Further the image plane's location is to be researched further
class ThinLensCamera
{
public:

	// public data members - camera attributes
	Vector3 position;			// Camera position
	Vector3 direction;			// Direction at which camera looks at
	Vector3 up;					// UP direction for camera
	ONB camera_coord;			// Camera's own coordinate system

	// Image attributes
	int image_width;			// The width of the film
	int image_height;			// the height of the film
	int npixels_x;				// The number of pixels in horizontal axis
	int npixels_y;				// the number of pixels in vertical axis
	float pixel_x_offset;		// next pixel's x offset from current location
	float pixel_y_offset;		// next pixel's y offset from current location
	
	// Images coord system - 2d coord system basically
	Vector3 image_origin;
	Vector3 image_u;
	Vector3 image_v;
	
	// Focal length attributes of the thin lens
	float image_distance;		// distance of image plane from lens
	float Fb;					// focal point behind the lens;
	float Ff;					// focal point forward of the lens;
	Vector3 focalpoint_f;		// Forward focal point
	Vector3 focalpoint_b;		// backward focal point

	float lens_radius;			// radius of the thin lens. We will be generating sample values within the circle of this lens radius

	Plane principal_plane;	// Principal plane of the lens - assuming lens to centered around the camera origin

	// Constructor

	// Default constructor
	ThinLensCamera() {}

	// Explicit initialization of camera
	ThinLensCamera(Vector3 _pos, Vector3 _dir, Vector3 _up, Handedness hand, int iw, int ih, int npixels_x, int npixels_y, float image_dist, float radius, float focal_back, float focal_front);

	// Functions

	// Get a ray from the camera
	Ray3 GetRay(int pixel_x, int pixel_y);

	// Get raypacket from camera for the particular pixel
	RayPacket GetRay(int pixel_x, int pixel_y, int num_samples);
};

#endif